/*
   Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
   Original sources are available at www.latestbit.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package org.latestbit.smartobjects.core;

import java.io.IOException;
import java.nio.BufferUnderflowException;
import java.util.concurrent.TimeoutException;

import org.latestbit.smartobjects.IDestroyable;
import org.latestbit.smartobjects.IServerSkeleton;
import org.latestbit.smartobjects.network.ConnectionHandler;
import org.latestbit.smartobjects.network.IManagedStreamListener;
import org.latestbit.smartobjects.network.INetworkCommand;

/**
 * ICommandProcessor interface provides access to core element processing requests from network 
 * to registered server implementations or processing requests from client proxy stubs to network.
 * The command processor working with server skeletons (implementations of IServerSkeleton) 
 * and remote proxy client stubs (implementations of IRemoteSmartObject).
 * Usually this interface not used by applications and provides low-level API. 
 * @author abdulla-a
 *
 */
public interface ICommandProcessor extends IManagedStreamListener, IDestroyable {
	/**
	 * Sends a request in asynchronous manner to remote side specified by connection handler
	 * @param connectionHandler network connection handler (destination)
	 * @param request command/request
	 * @param handler response handler
	 * @param userObject user/application specified and linked with the request object
	 * @param timeoutInSec timeout for response
	 * @throws IOException
	 * @throws BufferUnderflowException
	 */
	public void sendAsyncRequest(
		ConnectionHandler connectionHandler,
		INetworkCommand request, 
		ICommandProcessorHandler handler, 
		Object userObject, 
		int timeoutInSec) 
			throws IOException, BufferUnderflowException;
	
	/**
	 * Send a request in synchronous manner to remote side specified by connection handler 
	 * @param connectionHandler network connection handler (destination)
	 * @param request command/request
	 * @param timeoutInSec timeout for response
	 * @return response
	 * @throws IOException
	 * @throws TimeoutException
	 * @throws InterruptedException
	 * @throws BufferUnderflowException
	 */
	public INetworkCommand sendSyncRequest( 
			ConnectionHandler connectionHandler,
			INetworkCommand request, 
			int timeoutInSec ) 
				throws IOException, TimeoutException, InterruptedException, BufferUnderflowException;
	
	/**
	 * Send a response/reply for incoming request
	 * @param connectionHandler network connection handler (destination)
	 * @param response response
	 * @throws IOException
	 */
	public void sendResponse (
		ConnectionHandler connectionHandler,
		INetworkCommand response)
			throws IOException;
	
	/**
	 * Subscription to incoming requests
	 * @param handler incoming request handler instance
	 * @param destinationFilter destination id (filter). When request processing this id must be equal to INetworkCommand.getDestination() 
	 */
	public void addRequestHandler ( ICommandProcessorHandler handler, String destinationFilter );
	
	/**
	 * Subscription to incoming requests
	 * @param handler incoming request handler instance
	 * @param destinationFilter destination id (filter). When request processing this id must be equal to INetworkCommand.getDestination()
	 * @param instanceIdFilter  instance id (filter). When request processing this id must be equal to INetworkCommand.getInstanceId()
	 */	
	public void addRequestHandler ( ICommandProcessorHandler handler, String destinationFilter, String instanceIdFilter );
	
	/**
	 * Subscription to incoming requests by all skeleton supported interfaces
	 * @param handler incoming request handler instance
	 * @param smartObject skeleton instance
	 */		
	public void addRequestHandler ( ICommandProcessorHandler handler, IServerSkeleton smartObject);
	
	/**
	 * Unsubscribes from incoming request the specified handler
	 * @param handler incoming request handler instance
	 */
	public void delRequestHandler ( ICommandProcessorHandler handler );

	/**
	 * Gets async calls storage size
	 * @return async calls storage size
	 */
	public int getAsyncCallsQueueSize();

}
